【HarekazeCTF2019】Easy Notes-代码审计

本文最后更新于:2023年8月25日 下午

[TOC]

[HarekazeCTF2019]Easy Notes-代码审计

登录之后有几个功能点,可以添加节点,然后使用Export导出

image-20230824205806589

我们查看源码,

我们发现想要拿到flag的条件时$_SESSION['admin']=true

image-20230824210223434

如果我们能够控制session文件,就可以拿到flag了

image-20230824210445088

我们发现session存储的文件改为了:/var/www/tmp

重点看export.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?php
require_once('init.php');

if (!is_logged_in()) {
redirect('/?page=home');
}

$notes = get_notes();

if (!isset($_GET['type']) || empty($_GET['type'])) {
$type = 'zip';
} else {
$type = $_GET['type'];
}

$filename = get_user() . '-' . bin2hex(random_bytes(8)) . '.' . $type;
$filename = str_replace('..', '', $filename); // avoid path traversal
$path = TEMP_DIR . '/' . $filename;

if ($type === 'tar') {
$archive = new PharData($path);
$archive->startBuffering();
} else {
// use zip as default
$archive = new ZipArchive();
$archive->open($path, ZIPARCHIVE::CREATE | ZipArchive::OVERWRITE);
}

for ($index = 0; $index < count($notes); $index++) {
$note = $notes[$index];
$title = $note['title'];
$title = preg_replace('/[^!-~]/', '-', $title);
$title = preg_replace('#[/\\?*.]#', '-', $title); // delete suspicious characters
$archive->addFromString("{$index}_{$title}.json", json_encode($note));
}

if ($type === 'tar') {
$archive->stopBuffering();
} else {
$archive->close();
}

header('Content-Disposition: attachment; filename="' . $filename . '";');
header('Content-Length: ' . filesize($path));
header('Content-Type: application/zip');
readfile($path);

这里可以看到,导出的文件也是写到/var/www/tmp目录下面,所以我们可以尝试session伪造一下,伪造一个session文件

1
2
3
$filename = get_user() . '-' . bin2hex(random_bytes(8)) . '.' . $type;
$filename = str_replace('..', '', $filename); // avoid path traversal
$path = TEMP_DIR . '/' . $filename;

get_user()会获取用户名,bin2hex(random_bytes(8))会生成16进制字符串,

如果我们用户名为sess_,并且$type=.,那么两个.会被替换为空,所以最终文件名就符合session文件的格式了,session文件名可控

那么看一下session内容可控吗:

1
$archive->addFromString("{$index}_{$title}.json", json_encode($note));

可控的

由于默认session_serialize_handler=php,那么序列化规则为:

处理器 对应的存储格式
php 键名 + 竖线 + 经过 serialize() 函数反序列处理的值

所以$_SESSION['admin']=true需要满足:

1
admin|b:1;

但是由于我们导出的文件中有一些内容,防止被污染,我们需要这么写:

1
|N;admin|b:1;

image-20230824211602859

添加之后导出:

1
/export.php?type=.

最后替换一下PHPSESSID为文件名:

image-20230824211719493


【HarekazeCTF2019】Easy Notes-代码审计
https://leekosss.github.io/2023/08/25/[HarekazeCTF2019]Easy Notes-代码审计/
作者
leekos
发布于
2023年8月25日
更新于
2023年8月25日
许可协议